#pragma once

#include "compi/serializer.h"

#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <functional>
#include <vector>

namespace compi
{
namespace frame
{

namespace detail
{
static constexpr std::uint32_t CRC32_TABLE[512] = {
    0x00000000u, 0x77073096u, 0xEE0E612Cu, 0x9909512Au, 0x076DC419u, 0x706AF48Fu,
    0xE963A535u, 0x9E6495A3u, 0x0EDB8832u, 0x79DCB8A4u, 0xE0D5E91Eu, 0x97D2D988u,
    0x09B64C2Bu, 0x7EB17CBDu, 0xE7B82D07u, 0x90BF1D91u, 0x1DB71064u, 0x6AB020F2u,
    0xF3B97148u, 0x84BE41DEu, 0x1ADAD47Du, 0x6DDDE4EBu, 0xF4D4B551u, 0x83D385C7u,
    0x136C9856u, 0x646BA8C0u, 0xFD62F97Au, 0x8A65C9ECu, 0x14015C4Fu, 0x63066CD9u,
    0xFA0F3D63u, 0x8D080DF5u, 0x3B6E20C8u, 0x4C69105Eu, 0xD56041E4u, 0xA2677172u,
    0x3C03E4D1u, 0x4B04D447u, 0xD20D85FDu, 0xA50AB56Bu, 0x35B5A8FAu, 0x42B2986Cu,
    0xDBBBC9D6u, 0xACBCF940u, 0x32D86CE3u, 0x45DF5C75u, 0xDCD60DCFu, 0xABD13D59u,
    0x26D930ACu, 0x51DE003Au, 0xC8D75180u, 0xBFD06116u, 0x21B4F4B5u, 0x56B3C423u,
    0xCFBA9599u, 0xB8BDA50Fu, 0x2802B89Eu, 0x5F058808u, 0xC60CD9B2u, 0xB10BE924u,
    0x2F6F7C87u, 0x58684C11u, 0xC1611DABu, 0xB6662D3Du, 0x76DC4190u, 0x01DB7106u,
    0x98D220BCu, 0xEFD5102Au, 0x71B18589u, 0x06B6B51Fu, 0x9FBFE4A5u, 0xE8B8D433u,
    0x7807C9A2u, 0x0F00F934u, 0x9609A88Eu, 0xE10E9818u, 0x7F6A0DBBu, 0x086D3D2Du,
    0x91646C97u, 0xE6635C01u, 0x6B6B51F4u, 0x1C6C6162u, 0x856530D8u, 0xF262004Eu,
    0x6C0695EDu, 0x1B01A57Bu, 0x8208F4C1u, 0xF50FC457u, 0x65B0D9C6u, 0x12B7E950u,
    0x8BBEB8EAu, 0xFCB9887Cu, 0x62DD1DDFu, 0x15DA2D49u, 0x8CD37CF3u, 0xFBD44C65u,
    0x4DB26158u, 0x3AB551CEu, 0xA3BC0074u, 0xD4BB30E2u, 0x4ADFA541u, 0x3DD895D7u,
    0xA4D1C46Du, 0xD3D6F4FBu, 0x4369E96Au, 0x346ED9FCu, 0xAD678846u, 0xDA60B8D0u,
    0x44042D73u, 0x33031DE5u, 0xAA0A4C5Fu, 0xDD0D7CC9u, 0x5005713Cu, 0x270241AAu,
    0xBE0B1010u, 0xC90C2086u, 0x5768B525u, 0x206F85B3u, 0xB966D409u, 0xCE61E49Fu,
    0x5EDEF90Eu, 0x29D9C998u, 0xB0D09822u, 0xC7D7A8B4u, 0x59B33D17u, 0x2EB40D81u,
    0xB7BD5C3Bu, 0xC0BA6CADu, 0xEDB88320u, 0x9ABFB3B6u, 0x03B6E20Cu, 0x74B1D29Au,
    0xEAD54739u, 0x9DD277AFu, 0x04DB2615u, 0x73DC1683u, 0xE3630B12u, 0x94643B84u,
    0x0D6D6A3Eu, 0x7A6A5AA8u, 0xE40ECF0Bu, 0x9309FF9Du, 0x0A00AE27u, 0x7D079EB1u,
    0xF00F9344u, 0x8708A3D2u, 0x1E01F268u, 0x6906C2FEu, 0xF762575Du, 0x806567CBu,
    0x196C3671u, 0x6E6B06E7u, 0xFED41B76u, 0x89D32BE0u, 0x10DA7A5Au, 0x67DD4ACCu,
    0xF9B9DF6Fu, 0x8EBEEFF9u, 0x17B7BE43u, 0x60B08ED5u, 0xD6D6A3E8u, 0xA1D1937Eu,
    0x38D8C2C4u, 0x4FDFF252u, 0xD1BB67F1u, 0xA6BC5767u, 0x3FB506DDu, 0x48B2364Bu,
    0xD80D2BD2u, 0xAF0A1B4Cu, 0x36034AF6u, 0x41047A60u, 0xDF60EFC3u, 0xA867DF55u,
    0x316E8EEFu, 0x4669BE79u, 0xCB61B38Du, 0xBC66831Du, 0x256FD2A0u, 0x5268E236u,
    0xCC0C7795u, 0xBB0B4703u, 0x220216B9u, 0x5505262Fu, 0xC5BA3BBEu, 0xB2BD0B28u,
    0x2BB45A92u, 0x5CB36A04u, 0xC2D7FFA7u, 0xB5D0CF31u, 0x2CD99E8Bu, 0x5BDEAE1Du,
    0x9B64C2B0u, 0xEC63F226u, 0x756AA39Cu, 0x026D930Au, 0x9C0906A9u, 0xEB0E363Fu,
    0x72076785u, 0x05005713u, 0x95BF4A82u, 0xE2B87A14u, 0x7BB12BAEu, 0x0CB61B38u,
    0x92D28E9Bu, 0xE5D5BE0Du, 0x7CBCE1B0u, 0x0BA6CAD6u, 0x94D4FA0Fu, 0xE3D3D2D9u,
    0x7D6A0DBBu, 0x0A00AE27u, 0x93D28E9Bu, 0xE4D5BE0Du, 0x7CDCEFB7u, 0x0BDBDF21u,
    0x86D3D2D4u, 0xF1D4E242u, 0x68DDB3F8u, 0x1FDA836Eu, 0x81BE16CDu, 0xF6B9265Bu,
    0x6FB077E1u, 0x18B74777u, 0x88085AE6u, 0xFF0F6A70u, 0x66063BCAu, 0x11010B5Cu,
    0x8F659EFFu, 0xF862AE69u, 0x616BFFD3u, 0x166CCF45u, 0xA00AE278u, 0xD70DD2EEu,
    0x4E048354u, 0x3903B3C2u, 0xA7672661u, 0xD06016F7u, 0x4969474Du, 0x3E6E77DBu,
    0xAED16A4Au, 0xD9D65ADCu, 0x40DF0B66u, 0x37D83BF0u, 0xA9BCAE53u, 0xDEBB9EC5u,
    0x47B2CF7Fu, 0x30B5FFE9u, 0xBDBDF21Cu, 0xCABAC28Au, 0x53B39330u, 0x24B4A3A6u,
    0xBAD03605u, 0xCDD70693u, 0x54DE5729u, 0x23D967BFu, 0xB3667A2Eu, 0xC4614AB8u,
    0x5D681B02u, 0x2A6F2B94u, 0xB40BBE37u, 0xC30C8EA1u, 0x5A05DF1Bu, 0x2D02EF8Du};

inline std::uint32_t
crc32_bytes(const std::byte * data, std::size_t size)
{
    std::uint32_t crc = 0xFFFFFFFFu;
    for (std::size_t i = 0; i < size; ++i)
    {
        std::uint8_t v = static_cast<std::uint8_t>(std::to_integer<unsigned char>(data[i]));
        crc = (crc >> 8) ^ CRC32_TABLE[(crc ^ v) & 0xFFu];
    }
    return crc ^ 0xFFFFFFFFu;
}

inline std::uint32_t
xxhash32_bytes(const std::byte * data, std::size_t size)
{
    const std::uint32_t PRIME32_1 = 0x9E3779B1u;
    const std::uint32_t PRIME32_2 = 0x85EBCA77u;
    const std::uint32_t PRIME32_3 = 0xC2B2AE3Du;
    const std::uint32_t PRIME32_4 = 0x27D4EB2Fu;
    const std::uint32_t PRIME32_5 = 0x165667B1u;
    std::uint32_t h32 = size >= 16 ? (PRIME32_1 + PRIME32_2) : PRIME32_5;
    std::size_t index = 0;
    auto read32 = [&](std::size_t pos) -> std::uint32_t
    {
        return (static_cast<std::uint32_t>(std::to_integer<unsigned char>(data[pos + 0])) << 0) |
               (static_cast<std::uint32_t>(std::to_integer<unsigned char>(data[pos + 1])) << 8) |
               (static_cast<std::uint32_t>(std::to_integer<unsigned char>(data[pos + 2])) << 16) |
               (static_cast<std::uint32_t>(std::to_integer<unsigned char>(data[pos + 3])) << 24);
    };

    while (index + 16 <= size)
    {
        std::uint32_t k1 = read32(index);
        std::uint32_t k2 = read32(index + 4);
        std::uint32_t k3 = read32(index + 8);
        std::uint32_t k4 = read32(index + 12);
        h32 += k1 * PRIME32_2;
        h32 = (h32 << 13) | (h32 >> 19);
        h32 *= PRIME32_1;
        h32 += k2 * PRIME32_2;
        h32 = (h32 << 13) | (h32 >> 19);
        h32 *= PRIME32_1;
        h32 += k3 * PRIME32_2;
        h32 = (h32 << 13) | (h32 >> 19);
        h32 *= PRIME32_1;
        h32 += k4 * PRIME32_2;
        h32 = (h32 << 13) | (h32 >> 19);
        h32 *= PRIME32_1;
        index += 16;
    }

    while (index + 4 <= size)
    {
        std::uint32_t k1 = read32(index);
        h32 += k1 * PRIME32_3;
        h32 = (h32 << 17) | (h32 >> 15);
        h32 *= PRIME32_4;
        index += 4;
    }

    while (index < size)
    {
        std::uint8_t k1 = static_cast<std::uint8_t>(std::to_integer<unsigned char>(data[index]));
        h32 += k1 * PRIME32_5;
        h32 = (h32 << 11) | (h32 >> 21);
        h32 *= PRIME32_1;
        ++index;
    }

    h32 ^= static_cast<std::uint32_t>(size);
    h32 ^= h32 >> 15;
    h32 *= PRIME32_2;
    h32 ^= h32 >> 13;
    h32 *= PRIME32_3;
    h32 ^= h32 >> 16;
    return h32;
}
} // namespace detail

// 数据类型枚举（统一 TLV 类型）
enum class DataType : std::uint8_t
{
    SERIALIZED_VECTOR = 0x01,
    RAW_BYTES = 0x02,
    METADATA = 0x03,
    RESERVED_04 = 0x04,
    RESERVED_05 = 0x05,
    RESERVED_06 = 0x06,
    RESERVED_07 = 0x07
};

// TLV 类型保留范围（约定）：
// - 0x01..0x03：标准类型（SERIALIZED_VECTOR / RAW_BYTES / METADATA）
// - 0x04..0x3F：协议扩展保留
// - 0x40..0x7F：Collectives 内部扩展（如分段类型）
// - 0x80..0xEF：用户自定义类型（跨库互通需约定）
// - 0xF0..0xFE：库内部保留（不对外使用）
// 约定：Collectives 使用 METADATA 承载 counts/displs 或分段信息。

// 标志位（可拓展）
struct Flags
{
    static constexpr std::uint16_t NONE = 0x0000;
    // 可选校验字段：置位则头部携带 4 字节校验值
    static constexpr std::uint16_t HAS_CHECKSUM = 0x0001;
    // 校验算法选择：置位为 xxHash32；未置位则为 CRC32
    static constexpr std::uint16_t CHECKSUM_XXHASH32 = 0x0002;
};

// 协议常量
static constexpr std::uint8_t PROTOCOL_VERSION = 1;
static constexpr std::uint32_t TLV_FRAME_MAGIC = 0x544C5646; // "TLVF"
static constexpr std::size_t TLV_FRAME_HEADER_SIZE =
    16; // 魔数4 + 版本1 + 数据类型1 + 标志2 + 长度8
static constexpr std::size_t TLV_FRAME_HEADER_WITH_CHECKSUM_SIZE = 20; // 基础头 + 校验4

// 统一帧头（TLV）
struct Header
{
    std::uint32_t magic{TLV_FRAME_MAGIC};
    std::uint8_t version{PROTOCOL_VERSION};
    std::uint8_t data_type{static_cast<std::uint8_t>(DataType::SERIALIZED_VECTOR)};
    std::uint16_t flags{Flags::NONE};
    std::uint64_t length{0};   // 数据长度（不含头）
    std::uint32_t checksum{0}; // 可选校验值（flags & HAS_CHECKSUM 时有效）

    Header() = default;
    Header(DataType type, std::uint64_t data_length, std::uint16_t header_flags = Flags::NONE)
        : magic(TLV_FRAME_MAGIC),
          version(PROTOCOL_VERSION),
          data_type(static_cast<std::uint8_t>(type)),
          flags(header_flags),
          length(data_length)
    {
    }

    // 基本有效性校验（设计期简版）
    bool is_valid() const noexcept
    {
        return magic == TLV_FRAME_MAGIC && version == PROTOCOL_VERSION;
    }
};

// 帧边界信息
struct Boundary
{
    std::size_t offset{0};
    std::size_t header_size{0};
    std::size_t data_size{0};
    std::size_t total_size{0};
    DataType data_type{DataType::SERIALIZED_VECTOR};
    std::uint16_t flags{Flags::NONE};

    bool is_valid() const noexcept
    {
        return total_size == header_size + data_size && header_size > 0;
    }
    std::size_t data_offset() const noexcept { return offset + header_size; }
    std::size_t end_offset() const noexcept { return offset + total_size; }
};

// 验证结果
enum class ValidationResult
{
    Valid,
    InvalidMagic,
    InvalidVersion,
    InvalidLength,
    InsufficientData,
    CorruptedData
};

// 错误帧记录与线程局部错误栈（用于边界检测阶段收集坏帧）
struct ErrorFrame
{
    std::size_t offset{0};
    std::size_t header_size{0};
    std::size_t data_size{0};
    ValidationResult reason{ValidationResult::CorruptedData};
    DataType data_type{DataType::SERIALIZED_VECTOR};
    std::uint16_t flags{Flags::NONE};
};

inline std::vector<ErrorFrame> &
error_stack_ref()
{
    thread_local static std::vector<ErrorFrame> s;
    return s;
}
inline void
push_error_frame(const ErrorFrame & e)
{
    error_stack_ref().push_back(e);
}
inline const std::vector<ErrorFrame> &
peek_error_frames()
{
    return error_stack_ref();
}
inline std::vector<ErrorFrame>
take_error_frames()
{
    auto & s = error_stack_ref();
    auto out = s;
    s.clear();
    return out;
}

// 帧格式统计
struct FormatStats
{
    std::size_t tlv_frames{0};
    std::size_t unknown_frames{0};
    std::size_t total_frames() const { return tlv_frames + unknown_frames; }
    void reset() { tlv_frames = unknown_frames = 0; }
};

// 基础协议 API
bool is_tlv_format(const std::vector<std::byte> & bytes, std::size_t offset = 0);

std::vector<Boundary> detect_boundaries(const std::vector<std::byte> & bytes,
                                        std::size_t start_offset = 0);
ValidationResult validate_frame(const std::vector<std::byte> & bytes, const Boundary & b);
std::vector<std::byte> extract_payload(const std::vector<std::byte> & bytes, const Boundary & b);
std::vector<std::byte> create_frame(DataType type,
                                    const std::vector<std::byte> & payload,
                                    std::uint16_t flags = Flags::NONE);

// 轻量构建器：根据入参（类型、标志、载荷）生成 TLV 帧
class FrameBuilder
{
public:
    FrameBuilder(DataType type, std::uint16_t flags, std::vector<std::byte> payload)
        : _payload(std::move(payload))
    {
        _hdr = Header(type, static_cast<std::uint64_t>(_payload.size()), flags);
    }

    const Header & header() const noexcept { return _hdr; }
    const std::vector<std::byte> & payload() const noexcept { return _payload; }

    std::vector<std::byte> to_bytes() const
    {
        std::vector<std::byte> out;
        const bool has_checksum = (_hdr.flags & Flags::HAS_CHECKSUM) != 0;
        const bool use_xxhash = (_hdr.flags & Flags::CHECKSUM_XXHASH32) != 0;
        const std::size_t header_size =
            has_checksum ? TLV_FRAME_HEADER_WITH_CHECKSUM_SIZE : TLV_FRAME_HEADER_SIZE;
        out.resize(header_size + _payload.size());

        auto write_u32 = [&](std::size_t pos, std::uint32_t v)
        {
            out[pos + 0] = static_cast<std::byte>(v & 0xFF);
            out[pos + 1] = static_cast<std::byte>((v >> 8) & 0xFF);
            out[pos + 2] = static_cast<std::byte>((v >> 16) & 0xFF);
            out[pos + 3] = static_cast<std::byte>((v >> 24) & 0xFF);
        };
        auto write_u16 = [&](std::size_t pos, std::uint16_t v)
        {
            out[pos + 0] = static_cast<std::byte>(v & 0xFF);
            out[pos + 1] = static_cast<std::byte>((v >> 8) & 0xFF);
        };
        auto write_u64 = [&](std::size_t pos, std::uint64_t v)
        {
            for (int i = 0; i < 8; ++i)
                out[pos + i] = static_cast<std::byte>((v >> (8 * i)) & 0xFF);
        };

        // 写 TLV 头（小端）
        write_u32(0, _hdr.magic);
        out[4] = static_cast<std::byte>(_hdr.version);
        out[5] = static_cast<std::byte>(_hdr.data_type);
        write_u16(6, _hdr.flags);
        write_u64(8, _hdr.length);
        if (has_checksum)
        {
            const std::uint32_t sum = use_xxhash
                                          ? detail::xxhash32_bytes(_payload.data(), _payload.size())
                                          : detail::crc32_bytes(_payload.data(), _payload.size());
            write_u32(16, sum);
        }

        // 写载荷
        if (!_payload.empty())
        {
            std::memcpy(out.data() + header_size, _payload.data(), _payload.size());
        }
        return out;
    }

private:
    Header _hdr;
    std::vector<std::byte> _payload;
};

// 生成不含校验的 TLV 头字节（小端），便于就地拼装帧
inline std::array<std::byte, TLV_FRAME_HEADER_SIZE>
make_header_bytes(DataType type, std::uint16_t flags, std::uint64_t length)
{
    std::array<std::byte, TLV_FRAME_HEADER_SIZE> out{};
    auto write_u32 = [&](std::size_t pos, std::uint32_t v)
    {
        out[pos + 0] = static_cast<std::byte>(v & 0xFF);
        out[pos + 1] = static_cast<std::byte>((v >> 8) & 0xFF);
        out[pos + 2] = static_cast<std::byte>((v >> 16) & 0xFF);
        out[pos + 3] = static_cast<std::byte>((v >> 24) & 0xFF);
    };
    auto write_u16 = [&](std::size_t pos, std::uint16_t v)
    {
        out[pos + 0] = static_cast<std::byte>(v & 0xFF);
        out[pos + 1] = static_cast<std::byte>((v >> 8) & 0xFF);
    };
    auto write_u64 = [&](std::size_t pos, std::uint64_t v)
    {
        for (int i = 0; i < 8; ++i)
            out[pos + i] = static_cast<std::byte>((v >> (8 * i)) & 0xFF);
    };

    write_u32(0, TLV_FRAME_MAGIC);
    out[4] = static_cast<std::byte>(PROTOCOL_VERSION);
    out[5] = static_cast<std::byte>(static_cast<std::uint8_t>(type));
    write_u16(6, flags);
    write_u64(8, length);
    return out;
}

// 轻量读取器：提供边界、载荷与校验
class FrameReader
{
public:
    FrameReader(const std::vector<std::byte> & bytes, std::size_t offset = 0)
        : _bytes(bytes), _offset(offset)
    {
        parse();
    }

    Boundary boundary() const noexcept { return _b; }

    std::vector<std::byte> payload() const
    {
        if (!_b.is_valid())
            return {};
        return std::vector<std::byte>(_bytes.begin() + _b.data_offset(),
                                      _bytes.begin() + _b.end_offset());
    }

    ValidationResult validate() const noexcept
    {
        if (!_parsed)
            return ValidationResult::CorruptedData;
        if (_b.header_size == 0)
            return ValidationResult::InsufficientData;
        if (_hdr.magic != TLV_FRAME_MAGIC)
            return ValidationResult::InvalidMagic;
        if (_hdr.version != PROTOCOL_VERSION)
            return ValidationResult::InvalidVersion;
        if (_hdr.length != _b.data_size)
            return ValidationResult::InvalidLength;
        // 可选校验核验
        if ((_hdr.flags & Flags::HAS_CHECKSUM) != 0)
        {
            const bool use_xxhash = (_hdr.flags & Flags::CHECKSUM_XXHASH32) != 0;
            const std::byte * payload_ptr = _bytes.data() + _b.data_offset();
            const std::size_t payload_size = _b.data_size;
            const std::uint32_t sum = use_xxhash ? detail::xxhash32_bytes(payload_ptr, payload_size)
                                                 : detail::crc32_bytes(payload_ptr, payload_size);
            if (sum != _hdr.checksum)
                return ValidationResult::CorruptedData;
        }
        return ValidationResult::Valid;
    }

private:
    void parse()
    {
        _parsed = false;
        _b = Boundary{};
        if (_bytes.size() < _offset + TLV_FRAME_HEADER_SIZE)
            return;

        auto read_u32 = [&](std::size_t pos) -> std::uint32_t
        {
            return (static_cast<std::uint32_t>(std::to_integer<unsigned char>(_bytes[pos + 0]))
                    << 0) |
                   (static_cast<std::uint32_t>(std::to_integer<unsigned char>(_bytes[pos + 1]))
                    << 8) |
                   (static_cast<std::uint32_t>(std::to_integer<unsigned char>(_bytes[pos + 2]))
                    << 16) |
                   (static_cast<std::uint32_t>(std::to_integer<unsigned char>(_bytes[pos + 3]))
                    << 24);
        };
        auto read_u16 = [&](std::size_t pos) -> std::uint16_t
        {
            return static_cast<std::uint16_t>(
                (static_cast<std::uint16_t>(std::to_integer<unsigned char>(_bytes[pos + 0])) << 0) |
                (static_cast<std::uint16_t>(std::to_integer<unsigned char>(_bytes[pos + 1])) << 8));
        };
        auto read_u64 = [&](std::size_t pos) -> std::uint64_t
        {
            std::uint64_t v = 0;
            for (int i = 0; i < 8; ++i)
            {
                v |= (static_cast<std::uint64_t>(std::to_integer<unsigned char>(_bytes[pos + i]))
                      << (8 * i));
            }
            return v;
        };

        _hdr.magic = read_u32(_offset + 0);
        _hdr.version =
            static_cast<std::uint8_t>(std::to_integer<unsigned char>(_bytes[_offset + 4]));
        _hdr.data_type = std::to_integer<unsigned char>(_bytes[_offset + 5]);
        _hdr.flags = read_u16(_offset + 6);
        _hdr.length = read_u64(_offset + 8);
        const bool has_checksum = (_hdr.flags & Flags::HAS_CHECKSUM) != 0;
        const std::size_t header_size =
            has_checksum ? TLV_FRAME_HEADER_WITH_CHECKSUM_SIZE : TLV_FRAME_HEADER_SIZE;
        if (has_checksum)
        {
            if (_bytes.size() < _offset + header_size)
                return;
            _hdr.checksum = read_u32(_offset + 16);
        }

        _b.offset = _offset;
        _b.header_size = header_size;
        _b.data_size = static_cast<std::size_t>(_hdr.length);
        _b.total_size = _b.header_size + _b.data_size;
        _b.data_type = static_cast<DataType>(_hdr.data_type);
        _b.flags = _hdr.flags;

        if (_bytes.size() < _offset + _b.total_size)
            return; // 数据不足

        _parsed = true;
    }

    const std::vector<std::byte> & _bytes;
    std::size_t _offset{0};
    Header _hdr{};
    Boundary _b{};
    bool _parsed{false};
};

template <typename T>
std::vector<std::byte>
pack_frame(const std::vector<T> & values,
           DataType type = DataType::SERIALIZED_VECTOR,
           std::uint16_t flags = Flags::NONE)
{
    auto payload = compi::serialize_to_byte_vector(values);
    FrameBuilder builder(type, flags, std::move(payload));
    return builder.to_bytes();
}

template <typename T>
std::size_t
unpack_single_frame(const std::vector<std::byte> & bytes,
                    std::size_t offset,
                    std::vector<T> & frame_elements)
{
    FrameReader reader(bytes, offset);
    if (reader.validate() != ValidationResult::Valid)
        return bytes.size();
    auto payload = reader.payload();
    if (reader.boundary().data_type == DataType::SERIALIZED_VECTOR)
    {
        auto vec = compi::deserialize<std::vector<T>>(payload);
        frame_elements = std::move(vec);
    }
    return reader.boundary().end_offset();
}

template <typename T>
std::vector<T>
unpack_range(const std::vector<std::byte> & bytes)
{
    std::vector<T> out;
    std::size_t offset = 0;
    while (offset < bytes.size())
    {
        std::vector<T> part;
        std::size_t next = unpack_single_frame<T>(bytes, offset, part);
        if (next <= offset)
            break;
        if (!part.empty())
        {
            out.insert(out.end(), part.begin(), part.end());
        }
        offset = next;
    }
    return out;
}

template <typename T, typename FrameHandler>
void
unpack_range_iteratively(const std::vector<std::byte> & bytes, FrameHandler && handler)
{
    std::size_t offset = 0;
    while (offset < bytes.size())
    {
        FrameReader reader(bytes, offset);
        auto b = reader.boundary();
        if (!b.is_valid())
            break;
        auto payload = reader.payload();
        std::vector<T> elems;
        if (b.data_type == DataType::SERIALIZED_VECTOR)
        {
            elems = compi::deserialize<std::vector<T>>(payload);
        }
        if (!handler(b, bytes, payload))
            break;
        offset = b.end_offset();
    }
}

// 过程式接口封装（按帧处理）
class Protocol final
{
public:
    using Handler = std::function<bool(const Boundary & boundary,
                                       const std::vector<std::byte> & frame_data,
                                       const std::vector<std::byte> & payload)>;

    static std::vector<Boundary> detect_frame_boundaries(const std::vector<std::byte> & bytes,
                                                         std::size_t start_offset = 0);
    static ValidationResult validate(const std::vector<std::byte> & bytes,
                                     const Boundary & boundary);
    static std::vector<std::byte> payload(const std::vector<std::byte> & bytes,
                                          const Boundary & boundary);
    static std::vector<std::byte> make_frame(DataType type,
                                             const std::vector<std::byte> & payload,
                                             std::uint16_t flags = Flags::NONE);
    static std::size_t
    process(const std::vector<std::byte> & bytes, Handler handler, std::size_t start_offset = 0);
    static std::uint32_t checksum(const std::vector<std::byte> & bytes, const Boundary & boundary);
};

// -----------------------------
// 内联实现
// -----------------------------

inline bool
is_tlv_format(const std::vector<std::byte> & bytes, std::size_t offset)
{
    if (bytes.size() < offset + 4)
        return false;
    auto read_u32 = [&](std::size_t pos) -> std::uint32_t
    {
        return (static_cast<std::uint32_t>(std::to_integer<unsigned char>(bytes[pos + 0])) << 0) |
               (static_cast<std::uint32_t>(std::to_integer<unsigned char>(bytes[pos + 1])) << 8) |
               (static_cast<std::uint32_t>(std::to_integer<unsigned char>(bytes[pos + 2])) << 16) |
               (static_cast<std::uint32_t>(std::to_integer<unsigned char>(bytes[pos + 3])) << 24);
    };
    return read_u32(offset) == TLV_FRAME_MAGIC;
}

inline std::vector<Boundary>
detect_boundaries(const std::vector<std::byte> & bytes, std::size_t start_offset)
{
    std::vector<Boundary> out;
    std::size_t offset = start_offset;
    while (offset < bytes.size())
    {
        if (bytes.size() - offset < 4)
            break;
        // 检测 TLV 帧
        if (is_tlv_format(bytes, offset))
        {
            FrameReader reader(bytes, offset);
            auto b = reader.boundary();
            if (!b.is_valid())
            {
                push_error_frame(ErrorFrame{offset,
                                            0,
                                            0,
                                            ValidationResult::InsufficientData,
                                            DataType::SERIALIZED_VECTOR,
                                            Flags::NONE});
                ++offset; // 逐字节推进，避免级联崩
            }
            else
            {
                auto vr = reader.validate();
                if (vr == ValidationResult::Valid)
                {
                    out.push_back(b);
                    offset = b.end_offset();
                }
                else
                {
                    push_error_frame(
                        ErrorFrame{offset, b.header_size, b.data_size, vr, b.data_type, b.flags});
                    ++offset;
                }
            }
            continue;
        }
        // 未知格式：退出
        break;
    }
    return out;
}

inline ValidationResult
validate_frame(const std::vector<std::byte> & bytes, const Boundary & b)
{
    if (!b.is_valid())
        return ValidationResult::InsufficientData;
    if (bytes.size() < b.end_offset())
        return ValidationResult::InsufficientData;
    // TLV 检验
    if (b.header_size == TLV_FRAME_HEADER_SIZE ||
        b.header_size == TLV_FRAME_HEADER_WITH_CHECKSUM_SIZE)
    {
        FrameReader reader(bytes, b.offset);
        return reader.validate();
    }
    return ValidationResult::CorruptedData;
}

inline std::vector<std::byte>
extract_payload(const std::vector<std::byte> & bytes, const Boundary & b)
{
    if (!b.is_valid() || bytes.size() < b.end_offset())
        return {};
    return std::vector<std::byte>(bytes.begin() + b.data_offset(), bytes.begin() + b.end_offset());
}

inline std::vector<std::byte>
create_frame(DataType type, const std::vector<std::byte> & payload, std::uint16_t flags)
{
    FrameBuilder builder(type, flags, std::vector<std::byte>(payload.begin(), payload.end()));
    return builder.to_bytes();
}

inline std::vector<Boundary>
Protocol::detect_frame_boundaries(const std::vector<std::byte> & bytes, std::size_t start_offset)
{
    return frame::detect_boundaries(bytes, start_offset);
}

inline ValidationResult
Protocol::validate(const std::vector<std::byte> & bytes, const Boundary & boundary)
{
    return frame::validate_frame(bytes, boundary);
}

inline std::vector<std::byte>
Protocol::payload(const std::vector<std::byte> & bytes, const Boundary & boundary)
{
    return frame::extract_payload(bytes, boundary);
}

inline std::vector<std::byte>
Protocol::make_frame(DataType type, const std::vector<std::byte> & payload, std::uint16_t flags)
{
    return frame::create_frame(type, payload, flags);
}

inline std::size_t
Protocol::process(const std::vector<std::byte> & bytes, Handler handler, std::size_t start_offset)
{
    auto bounds = detect_frame_boundaries(bytes, start_offset);
    std::size_t last_end = start_offset;
    for (const auto & b : bounds)
    {
        if (!b.is_valid())
            break;
        last_end = b.end_offset();
        std::vector<std::byte> frame_data(bytes.begin() + b.offset, bytes.begin() + b.end_offset());
        auto pl = extract_payload(bytes, b);
        if (!handler(b, frame_data, pl))
            break;
    }
    return last_end;
}

inline std::uint32_t
Protocol::checksum(const std::vector<std::byte> & bytes, const Boundary & boundary)
{
    if (!boundary.is_valid() || bytes.size() < boundary.end_offset())
        return 0u;
    if ((boundary.flags & Flags::HAS_CHECKSUM) == 0)
        return 0u;
    const bool use_xxhash = (boundary.flags & Flags::CHECKSUM_XXHASH32) != 0;
    const std::byte * data_ptr = bytes.data() + boundary.data_offset();
    const std::size_t payload_size = boundary.data_size;
    return use_xxhash ? detail::xxhash32_bytes(data_ptr, payload_size)
                      : detail::crc32_bytes(data_ptr, payload_size);
}

} // namespace frame
} // namespace compi
